﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using MouseExtender.Common;
using MouseExtender.Interfaces;
using MouseExtender.View;
using MouseExtender.View.Plugin;

namespace MouseExtender.Plugins.Item
{
    public interface IItemPlugin
    {
        IEnumerable<string> SupportedContentTypes();

        DataTemplate GetDataTemplate(string itemContentType);

        void ExecuteItemAction(IItem item);

        UserControl GetEditor(IItem item);
    }

    [Export(typeof(IItemPlugin))]
    public class ProgramItemPlugin : IItemPlugin
    {
        public IEnumerable<string> SupportedContentTypes()
        {
            return new[] { "Program", "Shortcut" };
        }

        public DataTemplate GetDataTemplate(string itemContentType)
        {
            return (DataTemplate)Application.Current.Resources["ProgramItemPlugin_" + itemContentType];
        }

        public void ExecuteItemAction(IItem item)
        {
            MessageBox.Show("should run a program now");
        }


        public UserControl GetEditor(IItem item)
        {
            return new ProgramItemEditor();
        }
    }

    [Export(typeof(IItemPlugin))]
    public class LinkItemPlugin : IItemPlugin
    {
        public IEnumerable<string> SupportedContentTypes()
        {
            return new[] { "Link" };
        }

        public DataTemplate GetDataTemplate(string itemContentType)
        {
            return (DataTemplate)Application.Current.Resources["LinkItemPlugin_" + itemContentType];
        }

        public void ExecuteItemAction(IItem item)
        {
            MessageBox.Show("should open url in browser");
        }


        public UserControl GetEditor(IItem item)
        {
            return new LinkItemEditor();
        }
    }

    public class ItemViewControl : ContentControl
    {
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            if (newContent != null)
            {
                IItem item = (IItem)newContent;
                DataTemplate itemTemplate = AppContext.PluginManager.GetItemTemplate(item.ContentType);
                ContentTemplate = itemTemplate;
            }
        }
    }

    public class PluginManager
    {
        public PluginManager()
        {

        }

        [ImportMany(typeof(IItemPlugin))]
        public IEnumerable<IItemPlugin> ItemPlugins { get; set; }

        private IItemPlugin FindItemPlugin(string contentType)
        {
            if (_contentTypeMapping.ContainsKey(contentType))
            {
                return _contentTypeMapping[contentType];
            }
            else
            {
                throw new ArgumentOutOfRangeException("content type not found - " + contentType);
            }
        }

        private Dictionary<string, IItemPlugin> _contentTypeMapping = new Dictionary<string, IItemPlugin>();

        internal void InitializePlugins()
        {
            foreach (var itemPlugin in ItemPlugins)
            {
                var supportedTypes = itemPlugin.SupportedContentTypes();
                foreach (var supportedType in supportedTypes)
                {
                    _contentTypeMapping.Add(supportedType, itemPlugin);
                }
            }
        }

        internal DataTemplate GetItemTemplate(string contentType)
        {
            IItemPlugin p = FindItemPlugin(contentType);
            return p.GetDataTemplate(contentType);
        }

        internal void ExecuteEditItem(IItem item)
        {
            //throw new NotImplementedException();
            IItemPlugin p = FindItemPlugin(item.ContentType);
            UserControl c = p.GetEditor(item);
            var editor = new EditItemView(c, item);
            GlobalServices.ModalService.NavigateTo(editor, delegate(bool returnValue)
            {
                if (returnValue)
                    MessageBox.Show("EditItemView saved item");
                else
                    MessageBox.Show("EditItemView cancelled changes");
            });


        }

        internal void ExecuteItemAction(IItem item)
        {
            IItemPlugin p = FindItemPlugin(item.ContentType);
            p.ExecuteItemAction(item);
        }
    }

    public static class AppContext
    {
        public static CompositionContainer Container { get; set; }

        public static void SatistyImports(object obj)
        {
            Container.SatisfyImportsOnce(obj);
        }

        public static PluginManager PluginManager { get; set; }

        public static List<IItem> LauncherItems { get; set; }
    }

    public class AppCommands
    {
        public ActionCommand EditItem { get; set; }
        public ActionCommand ClickItem { get; set; }

        public AppCommands()
        {
            EditItem = new ActionCommand()
                           {
                               ExecuteDelegate = (p) =>
                                {
                                    IItem item = p as IItem;
                                    if (item != null)
                                    {
                                        AppContext.PluginManager.ExecuteEditItem(item);
                                    }
                                }
                           };
            ClickItem = new ActionCommand()
                            {
                                ExecuteDelegate = (p) =>
                                {
                                    IItem item = p as IItem;
                                    if (item != null)
                                    {
                                        AppContext.PluginManager.ExecuteItemAction(item);
                                    }
                                }
                            };
        }
    }

    public delegate void BackNavigationEventHandler(bool dialogReturn);

    public interface IModalService
    {
        void NavigateTo(UserControl uc, BackNavigationEventHandler backFromDialog);
        void GoBackward(bool dialogReturnValue);
    }

    public interface IItemEditor
    {
        void SaveChanges(IItem item);
        void CancelChanges(IItem item);
    }
}
